﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Timers;
using System.Windows.Forms;
using ConfusedKitten.Common;
using ConfusedKitten.Data;
using ConfusedKitten.WinApi;
using Timer = System.Timers.Timer;

namespace ProSpider
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        /// <summary>
        ///  运行程序集合（程序名为key）
        /// </summary>
        private Dictionary<string, List<int>> _pids = new Dictionary<string, List<int>>();

        /// <summary>
        ///  运行的timer集合
        /// </summary>
        private Dictionary<string, Timer> _timers = new Dictionary<string, Timer>();

        /// <summary>
        ///  初始化扫描程序
        /// </summary>
        /// <param name="sender">事件监控对象</param>
        /// <param name="e">事件数据</param>
        private void ListenPro_Load(object sender, EventArgs e)
        {
            // 获取运行目录下文件
            DirectoryInfo files = new DirectoryInfo(ProjectHelper.ProjectDirectory());
            // 扫描文件夹下的exe文件
            foreach (DirectoryInfo dic in files.GetDirectories())
            {
                foreach (FileInfo file in dic.GetFiles())
                {
                    if (file.Extension.Equals(".exe") && !file.Name.Equals("ListenHotel"))
                    {
                        // 添加列
                        int index = dataGridViewX1.Rows.Add();
                        dataGridViewX1.Rows[index].Cells["proname"].Value = dic.Name + "\\" + file.Name;
                        dataGridViewX1.Rows[index].Cells["isable"].Value = true;
                        dataGridViewX1.Rows[index].Cells["interval"].Value = "2";
                        dataGridViewX1.Rows[index].Cells["intervalcell"].Value = "秒";
                        dataGridViewX1.Rows[index].Cells["maxnum"].Value = "5";
                        dataGridViewX1.Rows[index].Cells["runningnum"].Value = "0";
                        dataGridViewX1.Rows[index].Cells["maxtime"].Value = "20";// 单位分钟
                        dataGridViewX1.Rows[index].Cells["isshow"].Value = false;
                    }
                }
            }
        }

        /// <summary>
        ///  初始化计时器
        /// </summary>
        private void InitTimer()
        {
            foreach (DataGridViewRow dr in dataGridViewX1.Rows)
            {
                // 获取程序名称
                string proname = dr.Cells["proname"].Value.ToString();
                // 获取是否启用
                bool.TryParse(dr.Cells["isable"].Value.ToString(), out bool isable);
                // 获取启动间隔
                double.TryParse(dr.Cells["interval"].Value.ToString(), out double intervalvalue);
                // 获取当前程序计时器
                _timers.TryGetValue(proname, out Timer currenttimer);
                // 启动时间转换
                switch (dr.Cells["intervalcell"].Value.ToString())
                {
                    case "秒": break;
                    case "分钟":
                        intervalvalue = intervalvalue * 60; break;
                    case "小时":
                        intervalvalue = intervalvalue * 60 * 60; break;
                    case "天":
                        intervalvalue = intervalvalue * 60 * 60 * 24; break;
                }
                // 是否启用
                if (isable)
                {
                    // 当前程序没有计时器的情况
                    if (currenttimer == null)
                    {
                        // 初始化计时器
                        currenttimer = new Timer(intervalvalue * 1000);
                        // 添加计时触发事件
                        currenttimer.Elapsed += new ElapsedEventHandler((o, e) => Timettask(o, e, dr.Index));
                        // 计时开始
                        currenttimer.Start();
                        // 添加计时至计时器列表
                        _timers.Lay(proname, currenttimer);
                    }
                    // 有计时的情况，刷新计时间隔
                    else
                    {
                        currenttimer.Interval = intervalvalue * 1000;
                    }
                }
            }
        }

        /// <summary>
        ///  计时触发任务
        /// </summary>
        /// <param name="v">事件源</param>
        /// <param name="o">事件数据</param>
        /// <param name="index">行索引</param>
        private void Timettask(object v, object o, int index)
        {
            // 取得当前行
            DataGridViewRow dr = dataGridViewX1.Rows[index];
            // 获取是否启用
            bool.TryParse(dr.Cells["isable"].Value.ToString(), out bool isable);
            if (!isable) return;
            // 获取当前程序启动的任务集合
            _pids.TryGetValue(dr.Cells["proname"].Value.ToString(), out List<int> pros);
            // 获取当前行显示的运行任务数量
            int.TryParse(dr.Cells["runningnum"].Value.ToString(), out int runcount);
            // 获取当前行设置的可运行最大数量
            int.TryParse(dr.Cells["maxnum"].Value.ToString(), out int maxnum);
            // 获取当前行设置的是否显示
            bool.TryParse(dr.Cells["isshow"].Value.ToString(), out bool isshow);
            // 当前程序运行达到最大数量的情况，返回
            if (pros != null && pros.Count >= maxnum) return;
            // 设置启动程序信息
            ProcessStartInfo startInfo = new ProcessStartInfo(dr.Cells["proname"].Value.ToString());
            // 设置显示/隐藏
            if (isshow) startInfo.WindowStyle = ProcessWindowStyle.Hidden;
            if (pros == null)
            {
                // 初始化程序运行集合
                pros = new List<int>();
            }
            LogHelper.Write("T_T", $"--{index}--开始{TimeHelper.NowToHms()}");
            // 启动程序
            Process p = Process.Start(startInfo);
            // 程序终止是触发事件
            p.EnableRaisingEvents = true;
            // 添加当前启动程序的pid
            pros.Add(p.Id);
            // 刷新当前任务集合记录列表
            _pids.Lay(dr.Cells["proname"].Value.ToString(), pros);
            LogHelper.Write("T_T", $"--{index}--结束{TimeHelper.NowToHms()}{pros.Count}");
            // 设置程序退出事件
            p.Exited += new EventHandler((a, e) => processexit(a, e, dr.Index));
            // 刷新运行程序数量
            dr.Cells["runningnum"].Value = pros.Count;
            // 刷新最新启动时间
            dr.Cells["LatestTime"].Value = TimeHelper.NowToHms();
        }

        /// <summary>
        ///  程序终止触发事件
        /// </summary>
        /// <param name="o">事件源</param>
        /// <param name="e">事件数据</param>
        /// <param name="index">行索引</param>
        private void processexit(object o, EventArgs e, int index)
        {
            // 获取当前行
            DataGridViewRow dr = dataGridViewX1.Rows[index];
            // 获取当前程序名称
            string proname = dr.Cells["proname"].Value.ToString();
            // 取得当前程序集合
            _pids.TryGetValue(proname, out List<int> pros);
            // 获取运行数量
            int.TryParse(dr.Cells["runningnum"].Value.ToString(), out int runcount);
            if (pros != null)
            {
                // 移除当前程序
                pros.Remove(((Process)o).Id);
                // 刷新当前运行程序数量
                runcount = pros.Count;
                dr.Cells["runningnum"].Value = pros.Count;
            }
            else
            {
                runcount = 0;
            }
        }

        /// <summary>
        ///  判断程序是否过期计时器
        /// </summary>
        private void AdjustTimer()
        {
            Timer protimer = new Timer(1000 * 10);
            protimer.Elapsed += Adjust;
            protimer.Start();
        }

        /// <summary>
        ///  遍历程序集合
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Adjust(object sender, ElapsedEventArgs e)
        {
            try
            {
                if (_pids == null) return;
                foreach (DataGridViewRow dr in dataGridViewX1.Rows)
                {
                    string proname = dr.Cells["proname"].Value.ToString();
                    _pids.TryGetValue(proname, out List<int> pros);
                    if (pros != null)
                    {
                        for (int i = 0; i < pros.Count; i++)
                        {
                            bool iseffective = AdjustProcess(pros[i], dr);
                            if (iseffective) continue;
                            else
                            {
                                if (pros.Contains(pros[i]))
                                {
                                    pros.Remove(pros[i]);
                                    _pids.Lay(dr.Cells["proname"].Value.ToString(), pros);
                                    dr.Cells["runningnum"].Value = pros.Count;
                                }
                            }
                        }
                    }
                }
            }
            catch
            {

            }
        }

        /// <summary>
        ///  判断当前程序是否超时
        /// </summary>
        /// <param name="proid">程序id</param>
        /// <param name="dr">当前行</param>
        /// <param name="pros">当前行的程序集合</param>
        private bool AdjustProcess(int proid, DataGridViewRow dr)
        {
            try
            {
                Process pro = Process.GetProcessById(proid);
                if (pro.HasExited)
                {
                    return false;
                }
                else
                {
                    double.TryParse(dr.Cells["maxtime"].Value.ToString(), out double maxmin);
                    TimeSpan times = ProcessHelper.GetProLiveTIme(proid);
                    if (times.TotalMinutes >= maxmin)
                    {
                        pro.Kill();
                        return false;
                    }
                    return true;
                }
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        ///  刷新
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonX2_Click(object sender, EventArgs e)
        {
            InitTimer();
            MessageBox.Show("刷新成功");
        }

        /// <summary>
        ///  单元格内容点击事件（最后两列可编辑，其他不可编辑）
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void dataGridViewX1_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex != -1)
            {
                // 取得当前单元格对应的列名.
                string columnName = dataGridViewX1.Columns[e.ColumnIndex].Name;

                // 是任务名称列的场合.
                if (!"proname".Equals(columnName) && !"runningnum".Equals(columnName))
                {
                    dataGridViewX1.CurrentCell.ReadOnly = false;
                    dataGridViewX1.CurrentCell.Tag = dataGridViewX1.CurrentCell.Value;
                }
                else
                {
                    dataGridViewX1.CurrentCell.ReadOnly = true;
                }
            }
        }

        /// <summary>
        ///  还原事件（取消情况回复原始设置，确认扫描列表）
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click_1(object sender, EventArgs e)
        {
            DialogResult result = MessageBox.Show("确认还原？", "确认还原", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
            if (result == DialogResult.OK)
            {
                for (int i = 0; i < dataGridViewX1.Rows.Count; i++)
                {
                    dataGridViewX1.Rows[i].Cells["isable"].Value = dataGridViewX1.Rows[i].Cells["isable"].Tag;
                    dataGridViewX1.Rows[i].Cells["interval"].Value = dataGridViewX1.Rows[i].Cells["interval"].Tag; ;
                    dataGridViewX1.Rows[i].Cells["intervalcell"].Value = dataGridViewX1.Rows[i].Cells["intervalcell"].Tag; ;
                    dataGridViewX1.Rows[i].Cells["maxnum"].Value = dataGridViewX1.Rows[i].Cells["maxnum"].Tag; ;
                    dataGridViewX1.Rows[i].Cells["runningnum"].Value = dataGridViewX1.Rows[i].Cells["runningnum"].Tag; ;
                    dataGridViewX1.Rows[i].Cells["maxtime"].Value = dataGridViewX1.Rows[i].Cells["maxtime"].Tag; ;
                }
            }
        }

        /// <summary>
        ///  运行事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonX1_Click(object sender, EventArgs e)
        {
            InitTimer();
        }

        /// <summary>
        ///  单元格改变立即提交
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void dataGridViewX1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
        {
            dataGridViewX1.CommitEdit(DataGridViewDataErrorContexts.Commit);
        }

        /// <summary>
        ///  校正程序
        /// </summary>
        /// <param name="sender">事件源</param>
        /// <param name="e">事件数据</param>
        private void buttonX4_Click(object sender, EventArgs e)
        {
            Adjust(null, null);
            MessageBox.Show("校正成功");
        }

        private void buttonX5_Click(object sender, EventArgs e)
        {
            ProcessStartInfo startInfo = new ProcessStartInfo("test\\HotelSchedule.exe");
            //// 设置显示/隐藏
            //if (isshow) startInfo.WindowStyle = ProcessWindowStyle.Hidden;
            // 启动程序
            Process p = Process.Start("HotelSchedule.exe");
        }
    }
}
